package com.jdd.modules.sentrybox.controller;

import cn.hutool.core.collection.CollUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.jdd.common.api.vo.Result;
import com.jdd.common.aspect.annotation.*;
import com.jdd.common.constant.CommonConstant;
import com.jdd.common.system.util.JwtUtil;
import com.jdd.common.util.CacheUtil;
import com.jdd.common.util.PasswordUtil;
import com.jdd.common.util.encryption.AesEncryptUtil;
import com.jdd.common.util.encryption.RASUtil;
import com.jdd.modules.operationLog.entity.ParkHandOverLog;
import com.jdd.modules.operationLog.mapper.ParkHandOverLogMapper;
import com.jdd.modules.parking.entity.ParkInfo;
import com.jdd.modules.parking.entity.ParkWorkStation;
import com.jdd.modules.parking.mapper.ParkWorkStationMapper;
import com.jdd.modules.parking.service.IParkInfoService;
import com.jdd.modules.system.entity.SysUser;
import com.jdd.modules.system.model.SysLoginModel;
import com.jdd.modules.system.service.ISysUserService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;


/**
 * @Description: 岗亭登录控制器
 * @author: ZhuLiuWei
 * @date: 2022/2/11 17:38
 */
@Slf4j
@RestController
@RequestMapping("/sentryBox")
@Api(tags = "岗亭用户登录")
public class SentryBoxLoginController {

    @Resource
    private ISysUserService sysUserService;
    @Resource
    private CacheUtil cacheUtil;
    @Resource
    private IParkInfoService parkInfoService;
    @Resource
    private ParkWorkStationMapper parkWorkStationMapper;
    @Resource
    private ParkHandOverLogMapper parkHandOverLogMapper;

    public static final int RESULT500 = 500;
    /**
     * 获取交接班操作员列表
     *
     * @return 用户刷新岗亭页面时校验当前工作站是否被别的用户占用
     */
    @GetMapping(value = "/refreshCheckInformation")
    @AutoLog(value = "用户刷新岗亭系统时校验当前工作站是否被别的用户占用")
    @ApiOperation(value = "用户刷新岗亭系统时校验当前工作站是否被别的用户占用", notes = "用户刷新岗亭系统时校验当前工作站是否被别的用户占用")
    public Result<Object> refreshCheckInformation(SysLoginModel sysLoginModel) {
        Result<Object> result = new Result<>();

        ParkWorkStation handOverUserList = parkWorkStationMapper.refreshCheckInformation(sysLoginModel);
        if (null==handOverUserList) {
            result.error500("工作站已被其他账号登录,请勿重新登录!");
            return result;
        }
        return Result.ok();
    }
    /**
     * 根据登录用户名获取离线工作站列表
     *
     * @param sysLoginModel 登录参数
     * @return 工作站列表 信息
     */
    @GetMapping(value = "/getParkWorkStationList")
    @AutoLog(value = "获取工作站列表")
    @ApiOperation(value = "获取工作站列表", notes = "获取工作站列表")
    public Result<List<ParkWorkStation>> getParkWorkStationList(SysLoginModel sysLoginModel) {
        Result<List<ParkWorkStation>> result = new Result<>();

        SysUser sysUser = sysUserService.getUserByName(sysLoginModel.getUsername());

        //校验用户是否有效
        Result<JSONObject> checkResult = sysUserService.checkUserIsEffective(sysUser);
        if (RESULT500 == checkResult.getCode() || !checkResult.isSuccess()) {
            result.error500(checkResult.getMessage());
            return result;
        }

        try {
            //校验数据的合法性
            if (StringUtils.isEmpty(sysUser.getSignature()) || !RASUtil.verifySign(sysUser.getSignature(), sysUser.getUsername())) {
                result.error500("该用户非法");
                return result;
            }
        } catch (Exception e) {
            log.error("用户非法登录---> {}", e.getMessage());
            result.error500("该用户非法");
            return result;
        }

        //工作站列表
        List<ParkWorkStation> workStationList = new ArrayList<>();

        //登录用户未交班的工作站
        LambdaQueryWrapper<ParkHandOverLog> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ParkHandOverLog::getOperationName, sysLoginModel.getUsername());
        wrapper.isNull(ParkHandOverLog::getHandOverName);
        wrapper.orderByDesc(ParkHandOverLog::getUpTime);
        wrapper.last("limit 1");
        ParkHandOverLog handOverLog = parkHandOverLogMapper.selectOne(wrapper);
        if (ObjectUtils.isNotEmpty(handOverLog)) {
            LambdaQueryWrapper<ParkWorkStation> stationWrapper = new LambdaQueryWrapper<>();
            stationWrapper.eq(ParkWorkStation::getOperationName, sysLoginModel.getUsername());
            stationWrapper.eq(ParkWorkStation::getWorkName, handOverLog.getWorkName());
            ParkWorkStation parkWorkStation = parkWorkStationMapper.selectOne(stationWrapper);
            workStationList.add(parkWorkStation);
        }

        //离线、未绑定的工作站及5分钟未更新updateTime的工作站
        List<ParkWorkStation> parkWorkStations = parkWorkStationMapper.getWorkStationList();
        if (ObjectUtils.isNotEmpty(parkWorkStations)) {
            workStationList.addAll(parkWorkStations);
        }

        if (ObjectUtils.isEmpty(workStationList)) {
            result.error500("工作站列表为空或者都在线!");
            return result;
        }
        result.setResult(workStationList.stream().distinct().collect(Collectors.toList()));
        return result;
    }

    /**
     * 岗亭登录
     *
     * @param sysLoginModel 登录参数
     * @return 登录结果
     * @throws Exception 异常信息
     */
    @PostMapping(value = "/login")
    @ApiOperation("登录接口")
    @OperationLogDetail(detail = "登录", level = LogLevelType.ONE, operationType = OperationType.LOGIN, operationUnit = OperationUnit.USER)
    public Result<JSONObject> login(@RequestBody SysLoginModel sysLoginModel) throws Exception {

        String oldPassword = sysLoginModel.getPassword().trim();
        String password = AesEncryptUtil.desEncrypt(URLDecoder.decode(oldPassword, CommonConstant.DEFAULT_CHARSET).replace(' ', '+'));

        if (StringUtils.isEmpty(password)) {
            password = oldPassword;
        }
        SysUser sysUser = sysUserService.getUserByName(sysLoginModel.getUsername());

        //校验用户是否有效
        Result<JSONObject> result = sysUserService.checkUserIsEffective(sysUser);
        if (RESULT500 == result.getCode() || !result.isSuccess()) {
            return result;
        }
        try {
            //校验数据的合法性
            if (StringUtils.isEmpty(sysUser.getSignature()) || !RASUtil.verifySign(sysUser.getSignature(), sysUser.getUsername())) {
                result.error500("该用户非法");
                return result;
            }
        } catch (Exception e) {
            log.error("用户非法登录---> {}", e.getMessage());
            result.error500("该用户非法");
            return result;
        }

        //校验用户名或密码是否正确
        String userPassword = PasswordUtil.encrypt(sysLoginModel.getUsername(), password, sysUser.getSalt());
        if (!sysUser.getPassword().equals(userPassword)) {
            result.error500("用户名或密码错误");
            return result;
        }

        //用户登录信息
        assembleUserInfo(sysUser, result);
        return result;
    }

    /**
     * 获取交接班操作员列表
     *
     * @return 交接班操作员列表
     */
    @GetMapping(value = "/getHandOverUserList")
    @AutoLog(value = "获取交接班操作员列表")
    @ApiOperation(value = "获取交接班操作员列表", notes = "获取交接班操作员列表")
    public Result<List<SysUser>> getHandOverUserList() {
        Result<List<SysUser>> result = new Result<>();

        List<SysUser> handOverUserList = sysUserService.getHandOverUserList();
        if (CollUtil.isEmpty(handOverUserList)) {
            result.error500("交接班操作员列表为空或者已有其他工作站!");
            return result;
        }
        result.setResult(handOverUserList);
        return result;
    }

    /**
     * 用户信息
     *
     * @param sysUser 用户信息
     * @param result  结果信息
     */
    private void assembleUserInfo(SysUser sysUser, Result<JSONObject> result) {
        String parkCode = "";
        String parkName = "";

        // 获取车场信息
        List<ParkInfo> list = parkInfoService.list();
        if (CollUtil.isNotEmpty(list)) {
            parkCode = list.get(0).getParkCode();
            parkName = list.get(0).getParkName();
        }

        // 生成token
        String token = JwtUtil.sign(sysUser.getUsername(), sysUser.getId(), parkCode, parkName, sysUser.getPassword());
        cacheUtil.put(CommonConstant.TOKEN_CACHE_NAME, CommonConstant.PREFIX_USER_TOKEN + sysUser.getId(), token);

        JSONObject obj = new JSONObject();
        obj.put("token", token);
        obj.put("userInfo", sysUser);
        result.setResult(obj);
        result.success("登录成功");
    }

}
